#!/bin/bash
# Basile Clout, July 2007
# Simulate virtual network for a given conf file containing the network host's IPs

#TODO: in Perl, these four funcitons in only one


pad=3
log="log.txt";:>$log
declare -a c1	#Cluster 1
declare -a c2	#Cluster 2

# Read command line
if [ $# -ne 2 ];then
	echo "Usage: $0 on/off hosts"
	exit
fi

mod=$1
hosts=$2
echo "# `date`" >> $log
echo -e "# $0 $* \n\n" >> $log



#~~~~~~~~~~~FUNCTIONS~~~~~~~~~~~~~


# Update routing table for nodes in one cluster,
# with gateway the c[0] of the cluster
# except router of c0 (c0[0])
# $1=local router, $2=remote cluster, $3 number of nodes in distant cluster
function minions {

	minions_addrt=''
	local route
	local lcr=$1
	declare -a local rc; rc=( `echo "$2"`)
	nrc=$3
	
	for (( j = 0; j < $nrc; j++ )); do
		route="ip route add ${rc[$j]} via ${lcr}; \n"
		minions_addrt="${minions_addrt}${route}"
	done
	
	route="ip route flush cache; \n"	#Flush the route cache
	minions_addrt="${minions_addrt}${route}"
	
	#echo -e "$minions_addrt"
}

# Update routing table for cluster's routers
function router {
	
	router_addrt=''
	local route
	local lcr=$1
	declare -a local rc; rc=( `echo "$2"`)
	nrc=$3
	
	for (( j = 1; j < $nrc; j++ )); do
		route="ip route add ${rc[$j]} via ${rc[0]};"
		router_addrt="${router_addrt}${route} \n"
	done
	
	rule_forward="echo 1 > /proc/sys/net/ipv4/ip_forward; \n"	#Enable ip forwarding for the router
	rule_redirect="echo 0 > /proc/sys/net/ipv4/conf/eth0/send_redirects; \n"	#Disable ICMP redirect for the router
	
	route="ip route flush cache; \n"	#Flush the route cache
	
	router_addrt="${router_addrt}${rule_forward}${rule_redirect}${route}"
	
	#echo -e "$router_addrt"
}



# Delete update for routing table for nodes in one cluster,
# with gateway the c[0] of the cluster
# except router of c0 (c0[0])
# $1=local router, $2=remote cluster, $3 number of nodes in distant cluster
function minions_del {

	minions_delrt=''
	local route
	local lcr=$1
	declare -a local rc; rc=( `echo "$2"`)
	nrc=$3
	
	for (( j = 0; j < $nrc; j++ )); do
		route="ip route delete ${rc[$j]} via ${lcr};"
		minions_delrt="${minions_delrt}${route} \n"
	done
	
	route="ip route flush cache; \n"	#Flush the route cache
	minions_delrt="${minions_delrt}${route}"
	
	#echo -e "$minions_delrt"
}

# Delete update routing table for cluster's routers
function router_del {
	
	router_delrt=''
	local route
	local lcr=$1
	declare -a local rc; rc=( `echo "$2"`)
	nrc=$3
	
	for (( j = 1; j < $nrc; j++ )); do
		route="ip route delete ${rc[$j]} via ${rc[0]};"
		router_delrt="${router_delrt}${route} \n"
	done
	
	rule_forward="echo 0 > /proc/sys/net/ipv4/ip_forward; \n"	#Enable ip forwarding for the router
	rule_redirect="echo 1 > /proc/sys/net/ipv4/conf/eth0/send_redirects; \n"	#Disable ICMP redirect for the router
	
	route="ip route flush cache; \n"	#Flush the route cache
	
	router_delrt="${router_delrt}${rule_forward}${rule_redirect}${route}"
	
	#echo -e "$router_delrt"
}

# Build the virtual network
function vlan_on {

	local rn		#Remote node
	
	rn=${c1[0]}
	echo -e "# Add routes for ${rn}\n" | tee -a $log
	echo -e $router_c1 >> $log
	ssh root@${rn} `echo -e "$router_c1"` >> $log
	
	for ((i=1; i<$nc1; i++)); do
		rn=${c1[$i]}
		echo -e "# Add routes for ${rn}\n" | tee -a $log
		echo -e $minions_c1 >> $log
		ssh root@${rn} `echo -e "$minions_c1"` >> $log
	done
	
	rn=${c2[0]}
	echo -e "# Add routes for ${rn}\n" | tee -a $log
	echo -e $router_c2 >> $log
	ssh root@${rn} `echo -e "$router_c2"` >> $log
	
	for ((i=1; i<$nc2; i++)); do
		rn=${c2[$i]}
		echo -e "# Add routes for ${rn}\n" | tee -a $log
		echo -e $minions_c2 >> $log
		ssh root@${rn} `echo -e "$minions_c2"` >> $log
	done
}

# Unbuild the virtual network
function vlan_off {

	local rn		#Remote node
	
	rn=${c1[0]}
	echo -e "# Deletes routes for ${rn}\n" | tee -a $log
	echo -e $router_c1_del >> $log
	ssh root@${rn} `echo -e "$router_c1_del"` >> $log
	
	for ((i=1; i<$nc1; i++)); do
		rn=${c1[$i]}
		echo -e "# Delete routes for ${rn}\n" | tee -a $log
		echo -e $minions_c1_del >> $log
		ssh root@${rn} `echo -e "$minions_c1_del"` >> $log
	done
	
	rn=${c2[0]}
	echo -e "# Delete routes for ${rn}\n" | tee -a $log
	echo -e $router_c2_del >> $log
	ssh root@${rn} `echo -e "$router_c2_del"` >> $log
	
	for ((i=1; i<$nc2; i++)); do
		rn=${c2[$i]}
		echo -e "# Delete routes for ${rn}\n" | tee -a $log
		echo -e $minions_c2_del >> $log
		ssh root@${rn} `echo -e "$minions_c2_del"` >> $log
	done
}


#~~~~~~~~~~~~~~MAIN~~~~~~~~~~~~~~~~~~

# Read host file
lines=( $(cat "$hosts") )
nh=${lines[0]}	#Number of hosts
nc1=${lines[1]}	#Number of nodes in c1
nc2=${lines[2]}	#Number of nodes in c2

# Node in c1
for ((i=0; i<$nc1; i+=1)); do
	c1[$i]=${lines[$(($i+$pad))]}
	#echo ${c1[$i]}
done

# Node in c2
for ((i=0; i<$nc2; i+=1)); do
	c2[$i]=${lines[$(($i+$pad+$nc1))]}
	#echo ${c2[$i]}
done

if [ $mod = "on" ];then
	
	# Determine routing tables for nodes within the clusters
	minions $c1 "`echo ${c2[@]}`" $nc2
	minions_c1=$minions_addrt
	minions $c2 "`echo ${c1[@]}`" $nc1
	minions_c2=$minions_addrt
	# For routers
	router $c1 "`echo ${c2[@]}`" $nc2
	router_c1=$router_addrt
	router $c2 "`echo ${c1[@]}`" $nc1
	router_c2=$router_addrt
	
	# Send the command to the nodes
	vlan_on
	
elif [ $mod = "off" ];then

	#Deleting added routes for minions
	minions_del $c1 "`echo ${c2[@]}`" $nc2
	minions_c1_del=$minions_delrt
	minions_del $c2 "`echo ${c1[@]}`" $nc1
	minions_c2_del=$minions_delrt
	#Deleting added routes and orders for routers
	router_del $c1 "`echo ${c2[@]}`" $nc2
	router_c1_del=$router_delrt
	router_del $c2 "`echo ${c1[@]}`" $nc1
	router_c2_del=$router_delrt
	
	# Send the command to the nodes
	vlan_off
else
	echo "Usage: $0 _on/off_ hosts"
	exit
fi

exit


